home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / serial / modem-st.0 / modem-st / modem-stats / modem-stats.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-21  |  5.1 KB  |  192 lines

  1. /* Send a command to a modem, and echo the modem's response.
  2.  *
  3.  * This program is typically used to document a modem's status after a
  4.  * connection, and may also be used to gather accounting statistics.
  5.  *
  6.  * This program may also be used to reset a modem,
  7.  * or send an initialization string to a modem.
  8.  *
  9.  * This program may be freely copied and used, as long as this header,
  10.  * the accompanying documentation, and the author's name remain intact.
  11.  *
  12.  * Copyright (c) 1995, Kenneth J. Hendrickson
  13.  *    kjh@usc.edu, kjh@seas.smu.edu
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <unistd.h>
  19. #include <signal.h>
  20.  
  21. #define    USAGE        "Usage: %s [-c command] [-e end_string] device\n"
  22.  
  23. #define    STRLEN        80
  24.  
  25. char    command[STRLEN+1] = "AT I6\r";    /* command to feed to modem */
  26. char    end_string[STRLEN+1] = "OK";    /* end of modem response */
  27. char    response[STRLEN+1];        /* response from modem */
  28.  
  29. char    *progname;            /* this program */
  30. char    *devname;            /* the modem name */
  31. FILE    *device;            /* the modem itself */
  32.  
  33. #define    ALARM        5        /* modem must respond in ALARM secs */
  34. int    alarms = 0;            /* number of times the alarm rang */
  35.  
  36. void    modem();            /* send command, print response */
  37. void    no_response();            /* timeout alarm handler */
  38.  
  39. int    optind;                /* used for counting options */
  40. char    *optarg;            /* used for holding option arguments */
  41.  
  42. int
  43. main(argc, argv)
  44. int    argc;
  45. char    **argv;
  46. {
  47.     int    opt;
  48.  
  49.     progname = argv[0];        /* set the program name */
  50.  
  51.     /* Parse the options. */
  52.     while ((opt = getopt(argc, argv, "c:e:")) != -1) {
  53.         switch (opt) {
  54.             case 'c':    /* modem command string */
  55.                 strncpy(command, optarg, STRLEN-1);
  56.                 strcat(command, "\r");
  57.                 break;
  58.             case 'e':    /* end of modem response */
  59.                 strncpy(end_string, optarg, STRLEN);
  60.                 /*strcat(end_string, "\r");*/
  61.                 /*strcat(end_string, "\n");*/
  62.                 break;
  63.             case ':':    /* missing option */
  64.             case '?':    /* unknown option character */
  65.             default:
  66.                 fprintf(stderr, USAGE, progname);
  67.                 exit(1);
  68.                 break;
  69.         }
  70.     }
  71.  
  72.     devname = argv[optind];        /* set the device name */
  73.     if (!devname) {
  74.         /* No device file was specified.  Give usage message. */
  75.         fprintf(stderr, USAGE, progname);
  76.         exit(1);
  77.     }
  78.  
  79.     /* Can we read and write to the device file? */
  80.     if ((device = fopen(devname, "r+")) == NULL) {
  81.         fprintf(stderr,
  82.             "%s: Can't open %s for reading and writing.\n",
  83.             progname, devname);
  84.         fprintf(stderr, USAGE, progname);
  85.         exit(1);
  86.     }
  87.  
  88.     /* Occasionally, after using the modem on a ppp or slip link,
  89.      * there will be garbage left over that may confuse modem-stats.
  90.      * Therefore, flush the garbage in a dry run with no output.
  91.      */
  92.     modem(0);
  93.  
  94.     modem(1);            /* Now do it for real. */
  95.     exit(0);            /* We succeeded. */
  96. }
  97.  
  98. void
  99. modem(print)
  100. int    print;                /* 0=dry run, 1=the real thing */
  101. {
  102.     int    command_len = strlen(command)-1;    /* ignore the '\r' */
  103.     int    end_len = strlen(end_string);
  104.     int    scan = 0;
  105.  
  106.     /* Output the command to the device. */
  107.     if (fputs(command, device) == EOF) {
  108.         fprintf(stderr,
  109.             "%s: Failure writing to %s.\n", progname, devname);
  110.         exit(1);
  111.     }
  112.     fflush(device);
  113.  
  114.     /* Set the alarm, in case the device doesn't answer. */
  115.     (void) signal(SIGALRM, no_response);
  116.     (void) alarm(ALARM);
  117.  
  118.     /* Read the device's response, and echo to stdout. */
  119.     while (fgets(response+scan, STRLEN-scan, device) != NULL) {
  120.         scan = 0;
  121.         /* Echo the response, up to and including end_string. */
  122.         while (strlen(response)-scan >= end_len) {
  123.             /* Remove any extra blank lines from output. */
  124.             if (print && strncmp(response+scan, "\n\n", 2) == 0) {
  125.                 fputc('\n', stdout);
  126.                 scan += 2;
  127.                 continue;
  128.             }
  129.             if (print && strncmp(response+scan, "\n\r\n", 3) == 0) {
  130.                 fputc('\n', stdout);
  131.                 scan += 3;
  132.                 continue;
  133.             }
  134.             /* Check for an echo of the command. */
  135.             if (strncmp(response+scan, command, command_len) == 0) {
  136.                 /* Ignore the echo of the command. */
  137.                 scan += command_len;
  138.                 if (response[scan] == '\r')
  139.                     scan++;
  140.                 if (response[scan] == '\n')
  141.                     scan++;
  142.                 continue;
  143.             }
  144.             /* Check for the terminating end_string */
  145.             if (strncmp(response+scan, end_string, end_len) == 0 &&
  146.                 (response[scan+end_len] == '\r' ||
  147.                  response[scan+end_len] == '\n') &&
  148.                 /* Don't be fooled by OFF HOOK messages. */
  149.                 (scan == 0 || response[scan-1] == '\n')) {
  150.                 /* We found end_string.  We're done. */
  151.                 (void) alarm(0);    /* reset the alarm */
  152.                 /* Don't print the end_string.
  153.                 if (print) {
  154.                     fputs(end_string, stdout);
  155.                     fputc('\n', stdout);
  156.                 } */
  157.                 return;
  158.             }
  159.             /* Response other than command echo or end_string */
  160.             if (print && response[scan] != '\r') {
  161.                 fputc(response[scan], stdout);
  162.             }
  163.             scan++;
  164.         }
  165.         /* Save what we haven't yet been able to process. */
  166.         memmove(response, response+scan, strlen(response+scan)+1);
  167.         scan = strlen(response);
  168.     }
  169.  
  170.     /* We encountered either EOF or an error.  Do nothing. */
  171. }
  172.  
  173. void
  174. no_response(i)
  175. int    i;
  176. {
  177.     alarms++;            /* The alarm went off again. */
  178.  
  179.     /* The device didn't respond within ALARM seconds. */
  180.  
  181.     if (alarms < 2) {
  182.         modem(1);        /* Try again, this time for real. */
  183.         exit(0);        /* This time we succeeded. */
  184.     } else {
  185.         /* We failed too many times. */
  186.         fprintf(stdout,
  187.             "%s: No response from %s.\n", progname, devname);
  188.         exit(3);
  189.     }
  190. }
  191.  
  192.